bitkeeper revision 1.1492 (428e3bd7k7u4q5iZW-q27Jpez3WzGg)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 20 May 2005 19:34:47 +0000 (19:34 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 20 May 2005 19:34:47 +0000 (19:34 +0000)
Clean up vbd probing, and include hardware sector size in the probe
information. blkback ensures that all requests are aligned to
hardware sector size and returns error if this is not so.
In blkfront we now have a request_queue per vbd, with hardsect_size
set appropriately.
It is now once again possible to mount a CDROM in a domU.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c
linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c
linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c
linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h
linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c
netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c
tools/blktap/parallax-threaded.c
tools/blktap/parallax.c
xen/include/public/io/blkif.h

index 530383dbf0f50c86ddea0ca354c2246c46139315..682906bf66c0126103ba500f534cec39284aa7c9 100644 (file)
@@ -136,11 +136,6 @@ static int xlvbd_init_device(vdisk_t *xd)
        major_name = XLSCSI_MAJOR_NAME;
        max_part   = XLSCSI_MAX_PART;
 
-    } else if (VDISK_VIRTUAL(xd->info)) {
-
-       major_name = XLVBD_MAJOR_NAME;
-       max_part   = XLVBD_MAX_PART;
-
     } else { 
 
         /* SMH: hmm - probably a CCISS driver or sim; assume CCISS for now */
@@ -247,8 +242,8 @@ static int xlvbd_init_device(vdisk_t *xd)
         blk_size[major] = gd->sizes;
     }
 
-    if ( VDISK_READONLY(xd->info) )
-        set_device_ro(device, 1); 
+    if ( xd->info & VDISK_READONLY )
+        set_device_ro(device, 1);
 
     gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XEN;
 
@@ -297,20 +292,16 @@ static int xlvbd_init_device(vdisk_t *xd)
         gd->sizes[minor] = capacity>>(BLOCK_SIZE_BITS-9);
         
         /* Some final fix-ups depending on the device type */
-        switch ( VDISK_TYPE(xd->info) )
+        if ( xd->info & VDISK_REMOVABLE )
         { 
-        case VDISK_TYPE_CDROM:
-        case VDISK_TYPE_FLOPPY: 
-        case VDISK_TYPE_TAPE:
             gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; 
             printk(KERN_ALERT 
                    "Skipping partition check on %s /dev/%s\n", 
-                   VDISK_TYPE(xd->info)==VDISK_TYPE_CDROM ? "cdrom" : 
-                   (VDISK_TYPE(xd->info)==VDISK_TYPE_TAPE ? "tape" : 
-                    "floppy"), disk_name(gd, MINOR(device), buf)); 
-            break; 
-
-        case VDISK_TYPE_DISK:
+                   (xd->info & VDISK_CDROM) ? "cdrom" : "removable",
+                   disk_name(gd, MINOR(device), buf)); 
+        }
+        else
+        {
             /* Only check partitions on real discs (not virtual!). */
             if ( gd->flags[minor>>gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
             {
@@ -320,12 +311,6 @@ static int xlvbd_init_device(vdisk_t *xd)
                 break;
             }
             register_disk(gd, device, gd->max_p, &xlvbd_block_fops, capacity);
-            break; 
-
-        default:
-            printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 
-                   VDISK_TYPE(xd->info)); 
-            break; 
         }
     }
 
index 40cd170e1d37a780baaa4784b67e91f0fddc376e..09ff8c245bae6e335370b10e0d6b2dd23a4fd3c3 100644 (file)
@@ -623,6 +623,13 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
 
     for ( i = 0; i < nseg; i++ )
     {
+        if ( ((int)preq.sector_number|(int)seg[i].nsec) &
+             ((bdev_hardsect_size(preq.bdev) >> 9) - 1) )
+        {
+            DPRINTK("Misaligned I/O request from domain %d", blkif->domid);
+            goto cleanup_and_fail;
+        }
+
         while ( (bio == NULL) ||
                 (bio_add_page(bio,
                               virt_to_page(MMAP_VADDR(pending_idx, i)),
@@ -632,6 +639,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
             bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
             if ( unlikely(bio == NULL) )
             {
+            cleanup_and_fail:
                 for ( i = 0; i < (nbio-1); i++ )
                     bio_put(biolist[i]);
                 fast_flush_area(pending_idx, nseg);
index d60a0126b704ec1ccf25c97bb463ef700fcf9121..2fcc42273ea36141085f4dfc6339b385d294ca19 100644 (file)
@@ -15,7 +15,7 @@
 struct vbd { 
     blkif_vdev_t   vdevice;     /* what the domain refers to this vbd as */
     unsigned char  readonly;    /* Non-zero -> read-only */
-    unsigned char  type;        /* VDISK_TYPE_xxx */
+    unsigned char  type;        /* VDISK_xxx */
     blkif_pdev_t   pdevice;     /* phys device that this vbd maps to */
     struct block_device *bdev;
     rb_node_t      rb;          /* for linking into R-B tree lookup struct */
@@ -30,6 +30,7 @@ static inline dev_t vbd_map_devnum(blkif_pdev_t cookie)
 #else
 #define vbd_sz(_v)   (blk_size[MAJOR((_v)->pdevice)][MINOR((_v)->pdevice)]*2)
 #define bdev_put(_b) ((void)0)
+#define bdev_hardsect_size(_b) 512
 #endif
 
 void vbd_create(blkif_be_vbd_create_t *create) 
@@ -78,6 +79,7 @@ void vbd_create(blkif_be_vbd_create_t *create)
 
     vbd->vdevice  = vdevice; 
     vbd->readonly = create->readonly;
+    vbd->type     = 0;
 
     /* Mask to 16-bit for compatibility with old tools */
     vbd->pdevice  = create->pdevice & 0xffff;
@@ -101,8 +103,11 @@ void vbd_create(blkif_be_vbd_create_t *create)
         return;
     }
 
-    vbd->type = (vbd->bdev->bd_disk->flags & GENHD_FL_CD) ?
-        VDISK_TYPE_CDROM : VDISK_TYPE_DISK;
+    if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD )
+        vbd->type |= VDISK_CDROM;
+    if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE )
+        vbd->type |= VDISK_REMOVABLE;
+
 #else
     if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) )
     {
@@ -110,8 +115,6 @@ void vbd_create(blkif_be_vbd_create_t *create)
         create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
         return;
     }
-
-    vbd->type = VDISK_TYPE_DISK;
 #endif
 
     spin_lock(&blkif->vbd_lock);
@@ -189,9 +192,10 @@ void destroy_all_vbds(blkif_t *blkif)
 static void vbd_probe_single(
     blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd)
 {
-    vbd_info->device   = vbd->vdevice; 
-    vbd_info->info     = vbd->type | (vbd->readonly ? VDISK_FLAG_RO : 0);
-    vbd_info->capacity = vbd_sz(vbd);
+    vbd_info->device      = vbd->vdevice; 
+    vbd_info->info        = vbd->type | (vbd->readonly ? VDISK_READONLY : 0);
+    vbd_info->capacity    = vbd_sz(vbd);
+    vbd_info->sector_size = bdev_hardsect_size(vbd->bdev);
 }
 
 
index 2276959ff76c3c10e134f0ccfa46b084d33b0ae1..7d1fb03ab6b756a0e8c8efd65d0fd46c90ef1bf0 100644 (file)
@@ -193,20 +193,21 @@ static void vbd_update(void)
 }
 #endif /* ENABLE_VBD_UPDATE */
 
+static struct xlbd_disk_info *head_waiting = NULL;
 static void kick_pending_request_queues(void)
 {
-    if ( (xlbd_blk_queue != NULL) &&
-         test_bit(QUEUE_FLAG_STOPPED, &xlbd_blk_queue->queue_flags) )
+    struct xlbd_disk_info *di;
+    while ( ((di = head_waiting) != NULL) && !RING_FULL(&blk_ring) )
     {
-        blk_start_queue(xlbd_blk_queue);
-        /* XXXcl call to request_fn should not be needed but
-         * we get stuck without...  needs investigating
-         */
-        xlbd_blk_queue->request_fn(xlbd_blk_queue);
+        head_waiting = di->next_waiting;
+        di->next_waiting = NULL;
+        /* Re-enable calldowns. */
+        blk_start_queue(di->rq);
+        /* Kick things off immediately. */
+        do_blkif_request(di->rq);
     }
 }
 
-
 int blkif_open(struct inode *inode, struct file *filep)
 {
     struct gendisk *gd = inode->i_bdev->bd_disk;
@@ -277,8 +278,7 @@ int blkif_ioctl(struct inode *inode, struct file *filep,
  */
 static int blkif_queue_request(struct request *req)
 {
-    struct xlbd_disk_info *di =
-        (struct xlbd_disk_info *)req->rq_disk->private_data;
+    struct xlbd_disk_info *di = req->rq_disk->private_data;
     unsigned long buffer_ma;
     blkif_request_t *ring_req;
     struct bio *bio;
@@ -353,6 +353,7 @@ static int blkif_queue_request(struct request *req)
  */
 void do_blkif_request(request_queue_t *rq)
 {
+    struct xlbd_disk_info *di;
     struct request *req;
     int queued;
 
@@ -369,10 +370,7 @@ void do_blkif_request(request_queue_t *rq)
         }
 
         if ( RING_FULL(&blk_ring) )
-        {
-            blk_stop_queue(rq);
-            break;
-        }
+            goto wait;
 
         DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
                 req, req->cmd, req->sector, req->current_nr_sectors,
@@ -382,7 +380,15 @@ void do_blkif_request(request_queue_t *rq)
         blkdev_dequeue_request(req);
         if ( blkif_queue_request(req) )
         {
-            blk_stop_queue(rq);
+        wait:
+            di = req->rq_disk->private_data;
+            if ( di->next_waiting == NULL )
+            {
+                di->next_waiting = head_waiting;
+                head_waiting = di;
+                /* Avoid pointless unplugs. */
+                blk_stop_queue(rq);
+            }
             break;
         }
 
@@ -451,7 +457,7 @@ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
     }
 
     blk_ring.rsp_cons = i;
-    
+
     kick_pending_request_queues();
 
     spin_unlock_irqrestore(&blkif_io_lock, flags);
index 459f9d95451ab6b23f7d2f293868b9c915d828cc..b1ade070262e2a7222db9ceb6ee760673e9e569e 100644 (file)
@@ -90,13 +90,16 @@ struct xlbd_major_info {
 struct xlbd_disk_info {
     int xd_device;
     struct xlbd_major_info *mi;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    struct xlbd_disk_info  *next_waiting;
+    request_queue_t        *rq;
+#endif
 };
 
 typedef struct xen_block {
     int usage;
 } xen_block_t;
 
-extern struct request_queue *xlbd_blk_queue;
 extern spinlock_t blkif_io_lock;
 
 extern int blkif_open(struct inode *inode, struct file *filep);
index 9a33656469541b0756ecd220ca900c76c986fadc..303d8ccae4c05e25b584e0a60078219a32bd33bd 100644 (file)
@@ -87,8 +87,6 @@ static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
 #define MAX_VBDS 64
 struct list_head vbds_list;
 
-struct request_queue *xlbd_blk_queue = NULL;
-
 #define MAJOR_XEN(dev) ((dev)>>8)
 #define MINOR_XEN(dev) ((dev) & 0xff)
 
@@ -233,35 +231,33 @@ static struct xlbd_major_info *xlbd_get_major_info(int device)
             xlbd_alloc_major_info(major, minor, index));
 }
 
-static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type)
+static int xlvbd_init_blk_queue(struct gendisk *gd, vdisk_t *disk)
 {
-    xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock);
-    if (xlbd_blk_queue == NULL)
-        return -1;
+    request_queue_t *rq;
 
-    elevator_init(xlbd_blk_queue, "noop");
+    rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
+    if (rq == NULL)
+        return -1;
 
-    /*
-    * Turn off barking 'headactive' mode. We dequeue
-    * buffer heads as soon as we pass them to back-end
-    * driver.
-    */
-    blk_queue_headactive(xlbd_blk_queue, 0);
+    elevator_init(rq, "noop");
 
     /* Hard sector size and max sectors impersonate the equiv. hardware. */
-    blk_queue_hardsect_size(xlbd_blk_queue, 512);
-    blk_queue_max_sectors(xlbd_blk_queue, 512);
+    blk_queue_hardsect_size(rq, disk->sector_size);
+    blk_queue_max_sectors(rq, 512);
 
     /* Each segment in a request is up to an aligned page in size. */
-    blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
-    blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
+    blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
+    blk_queue_max_segment_size(rq, PAGE_SIZE);
 
     /* Ensure a merged request will fit in a single I/O ring slot. */
-    blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
-    blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+    blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+    blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
     /* Make sure buffer addresses are sector-aligned. */
-    blk_queue_dma_alignment(xlbd_blk_queue, 511);
+    blk_queue_dma_alignment(rq, 511);
+
+    gd->queue = rq;
+
     return 0;
 }
 
@@ -274,19 +270,20 @@ struct gendisk *xlvbd_alloc_gendisk(
 
     di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
     if (di == NULL)
-        goto out;
+        return NULL;
+    memset(di, 0, sizeof(*di));
     di->mi = mi;
     di->xd_device = disk->device;
 
-    if ((VDISK_TYPE(disk->info) == VDISK_TYPE_DISK) &&
+    if (((disk->info & (VDISK_CDROM|VDISK_REMOVABLE)) == 0) &&
         ((minor & ((1 << mi->type->partn_shift) - 1)) == 0))
         nr_minors = 1 << mi->type->partn_shift;
 
     gd = alloc_disk(nr_minors);
-    if ( !gd )
+    if (gd == NULL)
         goto out;
 
-    if ((VDISK_TYPE(disk->info) != VDISK_TYPE_DISK) || (nr_minors > 1))
+    if (((disk->info & (VDISK_CDROM|VDISK_REMOVABLE)) != 0) || (nr_minors > 1))
         sprintf(gd->disk_name, "%s%c", mi->type->diskname,
                 'a' + mi->index * mi->type->disks_per_major +
                     (minor >> mi->type->partn_shift));
@@ -302,21 +299,26 @@ struct gendisk *xlvbd_alloc_gendisk(
     gd->private_data = di;
     set_capacity(gd, disk->capacity);
 
-    if ((xlbd_blk_queue == NULL) && xlvbd_blk_queue_alloc(mi->type))
-            goto out_gendisk;
+    if (xlvbd_init_blk_queue(gd, disk)) {
+        del_gendisk(gd);
+        goto out;
+    }
+
+    di->rq = gd->queue;
 
-    if (VDISK_READONLY(disk->info))
+    if (disk->info & VDISK_READONLY)
         set_disk_ro(gd, 1);
 
-    if (VDISK_TYPE(disk->info) == VDISK_TYPE_CDROM)
-        gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD;
+    if (disk->info & VDISK_REMOVABLE)
+        gd->flags |= GENHD_FL_REMOVABLE;
+
+    if (disk->info & VDISK_CDROM)
+        gd->flags |= GENHD_FL_CD;
 
-    gd->queue = xlbd_blk_queue;
     add_disk(gd);
+
     return gd;
 
-out_gendisk:
-    del_gendisk(gd);
 out:
     kfree(di);
     return NULL;
@@ -367,6 +369,7 @@ static int xlvbd_device_del(struct lvdisk *disk)
     struct gendisk *gd;
     struct xlbd_disk_info *di;
     int ret = 0, unused;
+    request_queue_t *rq;
 
     device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device));
 
@@ -383,7 +386,10 @@ static int xlvbd_device_del(struct lvdisk *disk)
         goto out;
     }
 
+    rq = gd->queue;
     del_gendisk(gd);
+    put_disk(gd);
+    blk_cleanup_queue(rq);
 
     xlvbd_device_free(disk);
 out:
index 23a96241d3772b7b188ef2f7ea9e00c62125b965..101332691ce98bfc9c0cc18d50dbcac49c30d38c 100644 (file)
@@ -476,17 +476,11 @@ get_xbda(vdisk_t *xd)
        case XEN_IDE7_MAJOR:
        case XEN_IDE8_MAJOR:
        case XEN_IDE9_MAJOR:
-               switch (VDISK_TYPE(xd->info)) {
-               case VDISK_TYPE_CDROM:
+               if (xd->info & VDISK_CDROM)
                        return &cd_ata;
-               case VDISK_TYPE_DISK:
-                       if (xd->capacity == 0)
-                               return NULL;
-                       return &wd_ata;
-               default:
+               if (xd->capacity == 0)
                        return NULL;
-               }
-               break;
+               return &wd_ata;
 #endif
        default:
                if (xd->capacity == 0)
index 47e469b111a40923d257961d2450587c1cf942bf..4944474fc774dcab2d6eebe8560088aec4c36146 100644 (file)
@@ -250,7 +250,7 @@ int parallax_probe(blkif_request_t *req, blkif_t *blkif)
         while (vdi) {
             img_info = (vdisk_t *)MMAP_VADDR(ID_TO_IDX(req->id), 0);
             img_info[nr_vdis].device   = vdi->vdevice;
-            img_info[nr_vdis].info     = VDISK_TYPE_DISK | VDISK_FLAG_VIRT;
+            img_info[nr_vdis].info     = 0;
             /* The -2 here accounts for the LSB in the radix tree */
             img_info[nr_vdis].capacity = 
                     ((1LL << (VDI_HEIGHT-2)) >> SECTOR_SHIFT);
index ee47957ada3312f24ebe0d7ff42a436cfdc2a975..dc71b05603fbec3ddb4aecbf0f7f6644090cddd3 100644 (file)
@@ -252,7 +252,7 @@ int parallax_probe(blkif_request_t *req, blkif_t *blkif)
         while (vdi) {
             img_info = (vdisk_t *)MMAP_VADDR(ID_TO_IDX(req->id), 0);
             img_info[nr_vdis].device   = vdi->vdevice;
-            img_info[nr_vdis].info     = VDISK_TYPE_DISK | VDISK_FLAG_VIRT;
+            img_info[nr_vdis].info     = 0;
             /* The -1 here accounts for the LSB in the radix tree */
             img_info[nr_vdis].capacity = 
                     ((1LL << (VDI_HEIGHT-1)) * SECTS_PER_NODE);
index 0f91912bbc715c9492bc7783b4ae5687af122b6e..9bc465cf1b5964b16ae0f74a4a38510ff70b3230 100644 (file)
@@ -83,26 +83,16 @@ DEFINE_RING_TYPES(blkif, blkif_request_t, blkif_response_t);
  * of vdisk_t elements.
  */
 
-/* XXX SMH: Type values below are chosen to match ide_xxx in Linux ide.h. */
-#define VDISK_TYPE_FLOPPY  0x00
-#define VDISK_TYPE_TAPE    0x01
-#define VDISK_TYPE_CDROM   0x05
-#define VDISK_TYPE_OPTICAL 0x07
-#define VDISK_TYPE_DISK    0x20 
-
-#define VDISK_TYPE_MASK    0x3F
-#define VDISK_TYPE(_x)     ((_x) & VDISK_TYPE_MASK) 
-
-/* The top two bits of the type field encode various flags. */
-#define VDISK_FLAG_RO      0x40
-#define VDISK_FLAG_VIRT    0x80
-#define VDISK_READONLY(_x) ((_x) & VDISK_FLAG_RO)
-#define VDISK_VIRTUAL(_x)  ((_x) & VDISK_FLAG_VIRT) 
+#define VDISK_CDROM        0x1
+#define VDISK_REMOVABLE    0x2
+#define VDISK_READONLY     0x4
 
-typedef struct {
+typedef struct vdisk {
     blkif_sector_t capacity;     /*  0: Size in terms of 512-byte sectors.   */
     blkif_vdev_t   device;       /*  8: Device number (opaque 16 bit value). */
     u16            info;         /* 10: Device type and flags (VDISK_*).     */
-} PACKED vdisk_t; /* 12 bytes */
+    u16            sector_size;  /* 12: Minimum alignment for requests.      */
+    u16            _pad;
+} PACKED vdisk_t; /* 16 bytes */
 
 #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */